package logging.transaction;

import org.mapdb.DB;

import storage.StorageException; // 假设此类可以提供DB实例

public class TransactionLogger {
    private static final TransactionLogger INSTANCE = new TransactionLogger();

    private DB currentTransactionDB;
    private String transactionDatabaseName;
    private String transactionOwnerName;
    private boolean transactionActive = false;

    // 私有构造函数，确保单例
    private TransactionLogger() {}

    public static TransactionLogger getInstance() {
        return INSTANCE;
    }

    /**
     * 为指定的数据库开始一个新的事务。
     * 如果当前已有为其他数据库激活的事务，会先尝试回滚该旧事务。
     * @param dbName 要开始事务的数据库名称
     * @param ownerName 数据库所有者的名称
     * @return true 如果事务成功开始, false 如果获取数据库实例失败或发生其他错误
     */
    public synchronized boolean beginTransaction(String ownerName, String dbName) {
        System.out.println("[TransactionLogger.beginTransaction] Called with Owner: '" + 
                           (ownerName == null ? "null" : ownerName) + "', DB Name: '" +
                           (dbName == null ? "null" : dbName) + "'");

        if (dbName == null || dbName.trim().isEmpty() || ownerName == null || ownerName.trim().isEmpty()) {
            System.err.println("错误: 数据库名称和所有者名称不能为空。");
            return false;
        }

        if (this.transactionActive) {
            if (this.transactionDatabaseName != null && 
                (!this.transactionDatabaseName.equals(dbName) || (this.transactionOwnerName != null && !this.transactionOwnerName.equals(ownerName)))) {
                System.out.println("提示: 存在为数据库 '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' 激活的事务，将先回滚它。");
                rollbackTransactionInternal(); // 回滚当前事务
            } else if (this.transactionDatabaseName != null) {
                System.out.println("提示: 数据库 '" + ownerName + "." + dbName + "' 的事务已激活。如需重新开始，请先COMMIT或ROLLBACK。");
                return true; 
            }
        }

        try {
            DB db = storage.manager.DatabaseManager.getDatabase(ownerName, dbName);

            System.out.println("[DEBUG] TransactionLogger: Received DB instance from DatabaseManager. Is null? " + (db == null));
            if (db != null) {
                 System.out.println("[DEBUG] TransactionLogger: DB instance state. Is closed? " + db.isClosed());
            } else {
                System.err.println("严重错误: DatabaseManager.getDatabase 返回了 null DB 实例给 TransactionLogger！");
                return false;
            }
            
            if (db.isClosed()){
                System.err.println("错误: DatabaseManager.getDatabase 为数据库 '" + ownerName + "." + dbName + "' 返回了一个已关闭的DB实例。无法启动事务。");
                return false;
            }
            
            this.currentTransactionDB = db;
            this.transactionDatabaseName = dbName;
            this.transactionOwnerName = ownerName;
            this.transactionActive = true;
            System.out.println("✅ 事务已为数据库 '" + ownerName + "." + dbName + "' 成功启动。");
            return true;
        } catch (StorageException se) { 
            System.err.println("错误: 获取数据库 '" + ownerName + "." + dbName + "' 实例时发生存储异常: " + se.getMessage());
            resetTransactionState();
            return false;
        } 
        catch (Exception e) {
            System.err.println("错误: 为数据库 '" + ownerName + "." + dbName + "' 启动事务时发生未知错误: " + e.getMessage());
            e.printStackTrace(); 
            resetTransactionState();
            return false;
        }
    }

    /**
     * 内部回滚方法，不打印给用户的成功/失败信息，主要用于事务切换。
     */
    private synchronized void rollbackTransactionInternal() {
        String dbNameToRelease = this.transactionDatabaseName; 
        String ownerNameToRelease = this.transactionOwnerName;
        boolean wasActive = this.transactionActive;

        if (this.currentTransactionDB != null && !this.currentTransactionDB.isClosed()) {
            try {
                this.currentTransactionDB.rollback();
                System.out.println("[DEBUG] TransactionLogger: Internal rollback for DB '" + ownerNameToRelease + "." + dbNameToRelease + "' successful.");
            } catch (Exception e) {
                System.err.println("内部回滚事务 '" + ownerNameToRelease + "." + dbNameToRelease + "' 时出错: " + e.getMessage());
            }
        }
        
        this.transactionActive = false; 

        if (wasActive && dbNameToRelease != null && ownerNameToRelease != null) {
            System.out.println("[DEBUG] TransactionLogger: Releasing database '" + ownerNameToRelease + "." + dbNameToRelease + "' due to internal rollback for transaction switch.");
            storage.manager.DatabaseManager.releaseDatabase(ownerNameToRelease, dbNameToRelease);
        }
    }

    /**
     * 提交当前活动的事务。
     * @return true 如果提交成功, false 如果没有活动事务或提交失败
     */
    public synchronized boolean commitTransaction() {
        if (!this.transactionActive) {
            System.err.println("错误: 没有活动的事务可提交。");
            return false;
        }
        if (this.currentTransactionDB == null || this.currentTransactionDB.isClosed()) {
            System.err.println("错误: 当前事务没有关联有效的数据库实例。");
            resetTransactionState(); // 清理无效状态
            return false;
        }

        try {
            this.currentTransactionDB.commit();
            System.out.println("事务已为数据库 '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' 成功提交。");
            resetTransactionState();
            return true;
        } catch (Exception e) {
            System.err.println("错误: 提交事务 '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' 时发生错误: " + e.getMessage());
            resetTransactionState(); 
            return false;
        }
    }

    /**
     * 回滚当前活动的事务。
     * @return true 如果回滚成功或没有活动事务, false 如果回滚操作本身失败
     */
    public synchronized boolean rollbackTransaction() {
        if (!this.transactionActive) {
            System.out.println("提示: 没有活动的事务可回滚。");
            return true; // 没有活动事务，视为回滚"成功"（无事可做）
        }
        if (this.currentTransactionDB == null || this.currentTransactionDB.isClosed()) {
            System.err.println("错误: 当前事务没有关联有效的数据库实例以执行回滚。");
            resetTransactionState();
            return false;
        }

        try {
            this.currentTransactionDB.rollback();
            System.out.println("事务已为数据库 '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' 成功回滚。");
            resetTransactionState();
            return true;
        } catch (Exception e) {
            System.err.println("错误: 回滚事务 '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' 时发生错误: " + e.getMessage());
            resetTransactionState(); 
            return false;
        }
    }

    public synchronized boolean isTransactionActive() {
        return this.transactionActive;
    }

    /**
     * 获取当前活动事务关联的DB实例。
     * @return 如果事务激活则返回DB实例，否则返回null。
     */
    public synchronized DB getCurrentTransactionDB() {
        if (!this.transactionActive) {
            return null;
        }
        return this.currentTransactionDB;
    }

    /**
     * 获取当前活动事务的数据库名称。
     * @return 如果事务激活则返回数据库名称，否则返回null。
     */
    public synchronized String getTransactionDatabaseName() {
        if (!this.transactionActive) {
            return null;
        }
        return this.transactionDatabaseName;
    }

    /**
     * 获取当前活动事务的数据库所有者名称。
     * @return 如果事务激活则返回数据库所有者名称，否则返回null。
     */
    public synchronized String getTransactionOwnerName() {
        if (!this.transactionActive) {
            return null;
        }
        return this.transactionOwnerName;
    }
    
    /**
     * 重置事务状态，通常在事务结束（提交或回滚）或发生严重错误后调用。
     */
    private synchronized void resetTransactionState() {
        if (this.transactionActive && this.transactionDatabaseName != null && this.transactionOwnerName != null) {
            System.out.println("[DEBUG] TransactionLogger: Releasing database '" + this.transactionOwnerName + "." + this.transactionDatabaseName + "' due to transaction end/reset.");
            storage.manager.DatabaseManager.releaseDatabase(this.transactionOwnerName, this.transactionDatabaseName);
        } else if (this.transactionDatabaseName != null && this.transactionOwnerName != null) {
            System.out.println("[WARN] TransactionLogger: Transaction was not marked active but had a DB name ('"+ this.transactionOwnerName + "." + this.transactionDatabaseName+"'). Attempting release.");
            storage.manager.DatabaseManager.releaseDatabase(this.transactionOwnerName, this.transactionDatabaseName);
        }
        
        this.currentTransactionDB = null; 
        this.transactionDatabaseName = null;
        this.transactionOwnerName = null;
        this.transactionActive = false;
        System.out.println("[DEBUG] TransactionLogger: Transaction state has been reset.");
    }

    /**
     * Clears the current database context for this session, typically after a transaction rollback.
     * This ensures the session state reflects that no database is actively selected if a transaction failed.
     */
    public void clearCurrentDatabaseAfterRollback() {
        if (this.transactionDatabaseName != null) { 
            System.out.println("[INFO] TransactionLogger: Transaction for database '" + (this.transactionOwnerName != null ? this.transactionOwnerName + "." : "") + this.transactionDatabaseName + "' was rolled back. Clearing current database context.");
        } else {
            System.out.println("[INFO] TransactionLogger: Transaction (potentially without a selected database) was rolled back. Ensuring database context is clear.");
        }
        this.transactionDatabaseName = null; 
        this.transactionOwnerName = null;
    }
}
